package cn.broadsense.biz.service.impl;

import cn.broadsense.biz.convert.CollectDataTaskConvert;
import cn.broadsense.biz.domain.Channel;
import cn.broadsense.biz.domain.Channel3dData;
import cn.broadsense.biz.domain.CollectDataTask;
import cn.broadsense.biz.domain.CollectDataTaskChannel;
import cn.broadsense.biz.dto.StatisticsTaskStatusDTO;
import cn.broadsense.biz.mapper.CollectDataTaskMapper;
import cn.broadsense.biz.service.Channel3dDataService;
import cn.broadsense.biz.service.ChannelService;
import cn.broadsense.biz.service.CollectDataTaskChannelService;
import cn.broadsense.biz.service.CollectDataTaskService;
import cn.broadsense.biz.utils.IdGenerationUtil;
import cn.broadsense.biz.vo.CollectDataTaskAuditVo;
import cn.broadsense.biz.vo.CollectDataTaskVo;
import cn.broadsense.common.annotation.DataScope;
import cn.broadsense.common.exception.ServiceException;
import cn.broadsense.common.utils.PageUtils;
import cn.broadsense.common.utils.SecurityUtils;
import cn.broadsense.common.utils.StringUtils;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.thread.ThreadUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;

/**
 * @author pengxin
 * @description 针对表【t_collect_data_task(数据采集任务)】的数据库操作Service实现
 * @createDate 2023-09-12 10:55:35
 */
@Service
public class CollectDataTaskServiceImpl extends ServiceImpl<CollectDataTaskMapper, CollectDataTask>
        implements CollectDataTaskService {

    @Resource
    private CollectDataTaskConvert dataTaskConvert;

    @Resource
    private ChannelService channelService;

    @Resource
    private CollectDataTaskChannelService dataTaskChannelService;

    @Resource
    private Channel3dDataService channel3dDataService;

    @Resource
    private CollectDataTaskMapper collectDataTaskMapper;


    private ExecutorService executorService = ThreadUtil.newFixedExecutor(50, 1024, "task-check-status", true);


    @Override
    @DataScope(deptAlias = "t")
    public List<CollectDataTask> findPage(CollectDataTask collectDataTask) {
        PageUtils.startPage();
        List<Long> taskIds = dataTaskChannelService.taskIdsSearchChannel(collectDataTask.getChannelName(), collectDataTask.getChannelSn());
        collectDataTask.setTaskIds(taskIds);
        List<CollectDataTask> list = this.collectDataTaskMapper.findList(collectDataTask);
        if (CollUtil.isNotEmpty(list)) {
            this.checkTaskStatus(null);
        }
        return list;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CollectDataTask addDataTask(CollectDataTaskVo dataTaskVo) {
        CollectDataTask collectDataTask = dataTaskConvert.toCollectDataTask(dataTaskVo);
        String taskNo = IdGenerationUtil.collectionTaskNo();
        collectDataTask.setCode(taskNo);
        List<Long> channelIds = dataTaskVo.getChannelIds();
        if (CollUtil.isEmpty(channelIds)) {
            throw new ServiceException("点位列表不能为空");
        }
        if (channelIds.size() > 10) {
            throw new ServiceException("点位最多不能超过10个");
        }
        //查询点位是否已经有关联任务

        collectDataTask.setDeptId(SecurityUtils.getDeptId());
        collectDataTask.setRemark(dataTaskVo.getRemarks());
        this.save(collectDataTask);
        insertTaskChannel(collectDataTask, channelIds);
        return collectDataTask;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(CollectDataTaskVo collectDataTaskVo) {
        CollectDataTask collectDataTask = dataTaskConvert.toCollectDataTask(collectDataTaskVo);
        collectDataTask.setId(collectDataTaskVo.getId());
        super.updateById(collectDataTask);
        removeChannelData(collectDataTaskVo.getId());

        insertTaskChannel(collectDataTask, collectDataTaskVo.getChannelIds());
    }

    @Override
    public boolean deleteById(Long id) {
        this.removeById(id);
        removeChannelData(id);
        return true;
    }


    @Override
    public CollectDataTask getDetails(Long id) {
        return this.getById(id);
    }

    @Override
    public Page<CollectDataTask> getUnfinishedTaskList(Page<CollectDataTask> page, CollectDataTask query) {
        LambdaQueryWrapper<CollectDataTask> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(CollectDataTask::getCollectUserId, SecurityUtils.getUserId());
        if (query.getStatus() != null) {
            if (!query.getStatus().equals(-1)) {
                queryWrapper.eq(CollectDataTask::getStatus, query.getStatus());
            }
        } else {
            if (query.getStatusList() != null && !query.getStatusList().isEmpty()) {
                if (!query.getStatusList().contains(-1)) {
                    queryWrapper.in(CollectDataTask::getStatus, query.getStatusList());
                }
            } else {
                queryWrapper.eq(CollectDataTask::getStatus, 1);
            }
        }
        if (query.getQueryStartTime() != null) {
            queryWrapper.ge(CollectDataTask::getEndTime, query.getQueryStartTime());
        }
        if (query.getQueryEndTime() != null) {
            queryWrapper.le(CollectDataTask::getEndTime, query.getQueryEndTime());
        }
        queryWrapper.like(StringUtils.isNotBlank(query.getName()), CollectDataTask::getName, query.getName());
        queryWrapper.orderByDesc(CollectDataTask::getCreateTime);
        return this.baseMapper.selectPage(page, queryWrapper);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void auditing(CollectDataTaskAuditVo taskAuditVo) {
        Long id = taskAuditVo.getId();
        CollectDataTask dataTask = getById(id);
        if (dataTask == null) {
            throw new ServiceException("任务不存在");
        }
        Date date = new Date();
        List<CollectDataTaskAuditVo> channelAuditList = taskAuditVo.getChannelAuditList();
        if (CollUtil.isEmpty(channelAuditList)) {
            throw new ServiceException("任务点位不存在");
        }

        if (CollUtil.isNotEmpty(channelAuditList)) {
            int status = 4;
            List<CollectDataTaskChannel> dataTaskChannelList = dataTaskChannelService.listByTaskId(taskAuditVo.getId());
            Map<Long, Integer> auditMap = channelAuditList.stream().collect(Collectors.toMap(CollectDataTaskAuditVo::getId, e -> e.getStatus()));
            for (CollectDataTaskChannel e : dataTaskChannelList) {
                e.setUpdateTime(date);
                e.setStatus(auditMap.get(e.getId()) == null ? 2 : auditMap.get(e.getId()));
                if (e.getStatus() != 1) {
                    status = 3;
                }
            }
            dataTask.setUpdateTime(date);
            dataTask.setStatus(status);
            dataTask.setUpdateBy(SecurityUtils.getUsername());
            dataTask.setReasonRejection(taskAuditVo.getReasonRejection());
            dataTask.setRejectTime(date);
            dataTask.setReviewTime(date);
            super.updateById(dataTask);

            dataTaskChannelService.updateBatchById(dataTaskChannelList);
            //审核通过 补充点位三维数据
            if (status == 4) {
                String username = SecurityUtils.getUsername();
                List<Channel3dData> addList = new ArrayList<>();
                //List<Long> channelIds = new ArrayList<>();
                dataTaskChannelList.forEach(e -> {
                    Channel3dData collectData = new Channel3dData();
                    BeanUtil.copyProperties(e.getCollectData(), collectData);
                    collectData.setChannelId(e.getChannelId());
                    collectData.setViewAngle(e.getCollectData().getViewAngle());
                    collectData.setRadius(e.getCollectData().getRadius()!=null? BigDecimal.valueOf(Double.parseDouble(e.getCollectData().getRadius())) : null);
                    collectData.setChannelName(e.getChannelName());



                    collectData.setCreateTime(date);
                    collectData.setUpdateTime(date);
                    collectData.setCreateBy(username);
                    collectData.setUpdateBy(username);
                    String s = JSONObject.toJSONString(e.getCollectData().getAttachment());
                    collectData.setAttachments(s);
                    //查询是否有3维数据
                    Channel3dData one = channel3dDataService.getOne(new LambdaQueryWrapper<Channel3dData>().eq(Channel3dData::getChannelId, e.getChannelId())
                            .orderByDesc(Channel3dData::getId).last("limit 1"));
                    if(one != null){
                        collectData.setId(one.getId());
                        collectData.setCreateTime(null);
                        collectData.setCreateBy(null);
                        channel3dDataService.updateById(collectData);
                    }else{
                    addList.add(collectData);
                    }
                    //channelIds.add(e.getChannelId());
                    LambdaUpdateWrapper<Channel> updateChannelWrapper = new LambdaUpdateWrapper<>();
                    updateChannelWrapper.set(e.getCollectData().getPole()!=null,Channel::getPole, e.getCollectData().getPole());
                    updateChannelWrapper.set(e.getCollectData().getPoleHeight()!=null,Channel::getPoleHeight, e.getCollectData().getPoleHeight());
                    updateChannelWrapper.set(e.getCollectData().getColumnGpsx()!=null,Channel::getGpsX, e.getCollectData().getColumnGpsx());
                    updateChannelWrapper.set(e.getCollectData().getColumnGpsy()!=null,Channel::getGpsY, e.getCollectData().getColumnGpsy());

                    updateChannelWrapper.set(Channel::getThreeDDataStatus, 2);
                    updateChannelWrapper.eq(Channel::getId, e.getChannelId());

                    channelService.update(updateChannelWrapper);
                });
                channel3dDataService.batchInsert(addList);

            }
        }
    }

    @Override
    public void checkTaskStatus(List<CollectDataTask> oldList) {
        executorService.execute(() -> {
            List<CollectDataTask> list = oldList;
            //没有值，查询所有未执行的
            if (CollUtil.isEmpty(list)) {
                LambdaQueryWrapper<CollectDataTask> query = new LambdaQueryWrapper<>();
                query.in(CollectDataTask::getTaskStatus, 1, 2);
                list = this.list(query);
            }
            if (CollUtil.isEmpty(list)) {
                return;
            }
            Date date = new Date();
            List<Long> ids = list.stream().filter(e -> DateUtil.compare(e.getEndTime(), date) < 0).map(CollectDataTask::getId).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(ids)) {
                UpdateWrapper<CollectDataTask> wrapper = new UpdateWrapper<>();
                wrapper.in("id", ids);
                wrapper.set("task_status", 3);
                wrapper.set("update_by", "system");
                wrapper.set("update_time", date);
                super.update(wrapper);
            }
        });
    }

    @Override
    public StatisticsTaskStatusDTO statisticsTaskStatus(Long collectUserId) {
        return this.baseMapper.statisticsTaskStatus(collectUserId);
    }

    /**
     * 添加任务点位
     *
     * @param collectDataTask
     * @param channelIds
     */
    private void insertTaskChannel(CollectDataTask collectDataTask, List<Long> channelIds) {
        List<Channel> channels = channelService.listByIds(channelIds);
        if (CollUtil.isEmpty(channels)) {
            throw new ServiceException("点位列表不能为空");
        }
        List<CollectDataTaskChannel> dataTaskChannelList = new ArrayList<>();
        Date date = new Date();
        for (Channel channel : channels) {
            CollectDataTaskChannel dataTaskChannel = new CollectDataTaskChannel();
            dataTaskChannel.setCollectDataTaskId(collectDataTask.getId());
            dataTaskChannel.setChannelId(channel.getId());
            dataTaskChannel.setChannelSn(channel.getChannelSn());
            dataTaskChannel.setChannelName(channel.getChannelName());
            dataTaskChannel.setStatus(0);
            dataTaskChannel.setUpdateTime(date);
            dataTaskChannelList.add(dataTaskChannel);
        }
        LambdaUpdateWrapper<Channel> updateChannelWrapper = new LambdaUpdateWrapper<>();
        updateChannelWrapper.set(Channel::getThreeDDataStatus, 3);
        updateChannelWrapper.in(Channel::getId, channelIds);
        channelService.update(updateChannelWrapper);
        dataTaskChannelService.saveBatch(dataTaskChannelList);
    }

    /**
     * 删除任务点位数据
     *
     * @param id
     */
    private void removeChannelData(Long id) {
        List<CollectDataTaskChannel> collectDataTaskList = dataTaskChannelService.getListByCollectDataTaskId(id);
        //删除点位数据
        if (CollUtil.isNotEmpty(collectDataTaskList)) {
            List<Long> channelIds = collectDataTaskList.stream().map(CollectDataTaskChannel::getChannelId).collect(Collectors.toList());
            LambdaUpdateWrapper<Channel> updateChannelWrapper = new LambdaUpdateWrapper<>();
            updateChannelWrapper.set(Channel::getThreeDDataStatus, 1);
            updateChannelWrapper.in(Channel::getId, channelIds);
            channelService.update(updateChannelWrapper);
        }
        //删除原有点位
        LambdaUpdateWrapper<CollectDataTaskChannel> deleteWrapper = new LambdaUpdateWrapper<>();
        deleteWrapper.eq(CollectDataTaskChannel::getCollectDataTaskId, id);
        dataTaskChannelService.remove(deleteWrapper);
    }
}




